home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / dtime / data.1 / Dtwinver.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-08  |  21.3 KB  |  625 lines

  1. /*
  2. Module : dtwinver.cpp
  3. Purpose: Implementation of a class to 
  4.          perform version detection on OS
  5. Created: PJN / DATE/2 / 11-05-1996
  6. History: None
  7.  
  8. Copyright (c) 1996 by PJ Naughter.  
  9. All rights reserved.
  10. */
  11.  
  12.  
  13. /////////////////////////////////  Includes  //////////////////////////////////
  14. #include "stdafx.h"
  15. #include "dtwinver.h"
  16. #include <stdarg.h>
  17.  
  18.  
  19. /////////////////////////////////  Local function / variables /////////////////
  20.  
  21.  
  22.  
  23. #ifndef _WIN32
  24.   //taken from Win32 sdk winbase.h file
  25.   #define VER_PLATFORM_WIN32s             0
  26.   #define VER_PLATFORM_WIN32_WINDOWS      1
  27.   #define VER_PLATFORM_WIN32_NT           2
  28. #else
  29.   BOOL WhichNTProduct(DWORD dwVersion);
  30. #endif
  31.                                      
  32.                                      
  33.                                      
  34.  
  35.  
  36.  
  37. #if defined(_WINDOWS) && !defined(_WIN32)     //required for universal thunks
  38.   #define HINSTANCE32              DWORD
  39.   #define HFILE32                  DWORD
  40.   #define HWND32                   DWORD
  41.  
  42.   // #defines for WOWCallProc32() parameter conversion
  43.   #define PARAM_01                 0x00000001
  44.  
  45.   // #defines for WOWGetCaps32()
  46.   #define WOW_LOADLIBRARY          0x0001
  47.   #define WOW_FREELIBRARY          0x0002
  48.   #define WOW_GETPROCADDRESS       0x0004
  49.   #define WOW_CALLPROC             0x0008
  50.   #define WOW_VDMPTR32             0x0010
  51.   #define WOW_VDMPTR16             0x0020
  52.   #define WOW_HWND32               0x0040
  53.  
  54.   // Wrappers for functions in Kernel (16 bit)
  55.   HINSTANCE32 WINAPI    WOWLoadLibraryEx32  (LPSTR, HFILE32, DWORD);
  56.   BOOL        WINAPI    WOWFreeLibrary32    (HINSTANCE32);
  57.   FARPROC     WINAPI    WOWGetProcAddress32 (HINSTANCE32, LPCSTR);
  58.   DWORD       WINAPI    WOWGetVDMPointer32  (LPVOID, UINT);
  59.   DWORD       FAR CDECL WOWCallProc32       (FARPROC, DWORD, DWORD, ...);
  60.  
  61.   DWORD       WINAPI    WOWGetCaps32         (VOID);
  62.   UINT        WINAPI    WOWCreateVDMPointer16(DWORD, DWORD);
  63.   UINT        WINAPI    WOWDeleteVDMPointer16(UINT);
  64.   HWND32      WINAPI    WOWHwndToHwnd32      (HWND);
  65.  
  66.  
  67.   //////////////// OSVERSIONINFO taken from Win32 sdk header file
  68.   typedef struct _OSVERSIONINFO
  69.   { 
  70.     DWORD dwOSVersionInfoSize; 
  71.     DWORD dwMajorVersion; 
  72.     DWORD dwMinorVersion; 
  73.     DWORD dwBuildNumber; 
  74.     DWORD dwPlatformId; 
  75.     TCHAR szCSDVersion[ 128 ]; 
  76.   } OSVERSIONINFO, *POSVERSIONINFO, FAR *LPOSVERSIONINFO; 
  77.  
  78.  
  79.   // Function pointers to stuff in Kernel (16 bit)
  80.   typedef HINSTANCE32 (WINAPI *lpfnLoadLibraryEx32W) (LPSTR, HFILE32, DWORD);
  81.   typedef BOOL        (WINAPI *lpfnFreeLibrary32W)   (HINSTANCE32);
  82.   typedef FARPROC     (WINAPI *lpfnGetProcAddress32W)(HINSTANCE32, LPCSTR);
  83.   typedef DWORD       (WINAPI *lpfnGetVDMPointer32W) (LPVOID, UINT);
  84.   typedef DWORD       (WINAPI *lpfnCallProc32W)      (FARPROC, DWORD, DWORD);
  85.   typedef WORD        (WINAPI *lpfnWNetGetCaps)      (WORD);
  86.  
  87.   lpfnLoadLibraryEx32W LoadLibraryEx32W;
  88.   lpfnFreeLibrary32W FreeLibrary32W;
  89.   lpfnGetProcAddress32W GetProcAddress32W;
  90.   lpfnGetVDMPointer32W GetVDMPointer32W;
  91.   lpfnCallProc32W CallProc32W;
  92.                
  93.   //capability bits               
  94.   DWORD dwCapBits;                                       
  95.  
  96.   BOOL WFWLoaded();
  97. #endif //defined(_WINDOWS) && !defined(_WIN32)
  98.  
  99.  
  100.  
  101.  
  102. #ifdef _DOS
  103.   BYTE WinMajor;
  104.   BYTE WinMinor;
  105.   WORD WinVer;
  106.   BYTE bRunningWindows;
  107.   void GetWinInfo();
  108. #endif
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115. //////////////////////////////////  Macros  ///////////////////////////////////
  116. #ifdef _DEBUG
  117. #undef THIS_FILE
  118. static char BASED_CODE THIS_FILE[] = __FILE__;
  119. #define new DEBUG_NEW
  120. #endif                                     
  121.  
  122.  
  123.  
  124.  
  125.  
  126. ////////////////////////////////// Implementation /////////////////////////////
  127.  
  128. BOOL EXPORT16 GetOSVersion(LPOS_VERSION_INFO lpVersionInformation)
  129. {                
  130.   //size field must be filled in prior to call,
  131.   //this is the same behaviour as the real Win32 api
  132.   if (lpVersionInformation->dwOSVersionInfoSize != sizeof(OS_VERSION_INFO))
  133.     return FALSE;            
  134.     
  135.   #ifdef _WIN32  //Nice and simple when on Win32
  136.     OSVERSIONINFO osvi;
  137.     memset(&osvi, 0, sizeof(OSVERSIONINFO));
  138.     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  139.     BOOL bSuccess = GetVersionEx(&osvi);
  140.     lpVersionInformation->dwEmulatedMajorVersion = osvi.dwMajorVersion; 
  141.     lpVersionInformation->dwEmulatedMinorVersion = osvi.dwMinorVersion; 
  142.     lpVersionInformation->dwEmulatedBuildNumber = LOWORD(osvi.dwBuildNumber); //ignore HIWORD
  143.     lpVersionInformation->dwEmulatedPlatformId = osvi.dwPlatformId;
  144.     _tcscpy(lpVersionInformation->szEmulatedCSDVersion, osvi.szCSDVersion);
  145.     
  146.     //Explicitely map the win32 dwPlatformId to our own values
  147.     if (lpVersionInformation->dwEmulatedPlatformId == VER_PLATFORM_WIN32s)
  148.       lpVersionInformation->dwEmulatedPlatformId = PLATFORM_WIN32S;
  149.     else if (lpVersionInformation->dwEmulatedPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  150.       lpVersionInformation->dwEmulatedPlatformId = PLATFORM_WINDOWS95;
  151.     if (lpVersionInformation->dwEmulatedPlatformId == VER_PLATFORM_WIN32_NT)
  152.       lpVersionInformation->dwEmulatedPlatformId = PLATFORM_NT_WORKSTATION;
  153.     
  154.     //Win32s is not an OS in its own right 
  155.     if (lpVersionInformation->dwEmulatedPlatformId == PLATFORM_WIN32S)
  156.     {                                     
  157.       //Could not find a method of determining what Win 16 version from within win32,
  158.       //so just assume Windows 3.10
  159.       lpVersionInformation->dwUnderlyingMajorVersion = 3; 
  160.       lpVersionInformation->dwUnderlyingMinorVersion = 10; 
  161.       lpVersionInformation->dwUnderlyingBuildNumber = 0;
  162.       lpVersionInformation->dwUnderlyingPlatformId = PLATFORM_WINDOWS;
  163.       _tcscpy(lpVersionInformation->szUnderlyingCSDVersion, _T("Microsoft Windows"));
  164.     }
  165.     else
  166.     { 
  167.       //determine which version on NT we're running                      
  168.       DWORD dwVersion=0;    
  169.       if (WhichNTProduct(dwVersion))
  170.       {
  171.         lpVersionInformation->dwUnderlyingPlatformId = dwVersion; 
  172.         lpVersionInformation->dwEmulatedPlatformId = dwVersion;
  173.       } 
  174.       lpVersionInformation->dwUnderlyingMajorVersion = osvi.dwMajorVersion; 
  175.       lpVersionInformation->dwUnderlyingMinorVersion = osvi.dwMinorVersion; 
  176.       lpVersionInformation->dwUnderlyingBuildNumber = LOWORD(osvi.dwBuildNumber); //ignore HIWORD
  177.       lpVersionInformation->dwUnderlyingPlatformId = osvi.dwPlatformId;
  178.       _tcscpy(lpVersionInformation->szUnderlyingCSDVersion, osvi.szCSDVersion);
  179.     }
  180.   #else //We must be runing on an emulated or real version of Win16 or Dos
  181.     #ifdef _WINDOWS //Running on some version of Windows                   
  182.       DWORD dwVersion = GetVersion();
  183.       // GetVersion does not differentiate between Windows 3.1 and Windows 3.11
  184.       
  185.       lpVersionInformation->dwEmulatedMajorVersion = LOBYTE(LOWORD(dwVersion)); 
  186.       lpVersionInformation->dwEmulatedMinorVersion = HIBYTE(LOWORD(dwVersion));
  187.       lpVersionInformation->dwEmulatedBuildNumber = 0; //no build number with Win3.1x
  188.       lpVersionInformation->dwEmulatedPlatformId = PLATFORM_WINDOWS;
  189.       strcpy(lpVersionInformation->szEmulatedCSDVersion, "Microsoft Windows");
  190.       
  191.       
  192.       //GetVersion returns 3.1 even on WFW, need to poke further
  193.       //to find the real difference                      
  194.       if (WFWLoaded())
  195.         lpVersionInformation->dwEmulatedPlatformId = PLATFORM_WINDOWSFW;
  196.  
  197.       //Call to get the underlying OS here through 16 -> 32 bit Generic Thunk
  198.       BOOL bFoundUnderlyingOS = FALSE;
  199.  
  200.       // Initialize capability bits for supplied functions
  201.       dwCapBits = WOW_VDMPTR16 | WOW_HWND32;
  202.     
  203.       // Get Kernel handle (we're already running in 16 bit mode so its
  204.       // gotta be loaded, right?!
  205.       HMODULE hKernel=GetModuleHandle("KERNEL");
  206.     
  207.       // Dynamically link to the functions we want, setting the capability
  208.       // bits as needed
  209.       LoadLibraryEx32W = ((lpfnLoadLibraryEx32W) (GetProcAddress(hKernel, "LoadLibraryEx32W")));
  210.       if (LoadLibraryEx32W)
  211.         dwCapBits |= WOW_LOADLIBRARY;
  212.            
  213.       FreeLibrary32W = ((lpfnFreeLibrary32W) (GetProcAddress(hKernel, "FreeLibrary32W")));
  214.       if (FreeLibrary32W)
  215.         dwCapBits |= WOW_FREELIBRARY;
  216.            
  217.       GetProcAddress32W = ((lpfnGetProcAddress32W) (GetProcAddress(hKernel, "GetProcAddress32W")));
  218.       if (GetProcAddress32W)
  219.         dwCapBits |= WOW_GETPROCADDRESS;
  220.            
  221.       GetVDMPointer32W = ((lpfnGetVDMPointer32W) (GetProcAddress(hKernel, "GetVDMPointer32W")));
  222.       if (GetVDMPointer32W)
  223.         dwCapBits |= WOW_VDMPTR32;
  224.            
  225.       CallProc32W = ((lpfnCallProc32W) (GetProcAddress(hKernel, "CallProc32W")));     
  226.       if (CallProc32W)
  227.         dwCapBits |= WOW_CALLPROC;
  228.  
  229.       //Call thro' the thunk to the Win32 function "GetVersionEx"
  230.       HINSTANCE32 hInstKrnl32 = WOWLoadLibraryEx32("KERNEL32.DLL", NULL, NULL);
  231.       //Because we are building the call to the function at runtime, We don't 
  232.       //forget to include the A at the end to call the ASCII version of GetVersionEx
  233.       FARPROC lpfnWin32GetVersionEx = WOWGetProcAddress32(hInstKrnl32, "GetVersionExA");
  234.       if (lpfnWin32GetVersionEx)
  235.       {              
  236.         OSVERSIONINFO osvi;                      
  237.         memset(&osvi, 0, sizeof(OSVERSIONINFO));
  238.         osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  239.         DWORD dwSuccess = WOWCallProc32(lpfnWin32GetVersionEx, PARAM_01, 1, &osvi);
  240.         if (dwSuccess)
  241.         {
  242.           lpVersionInformation->dwUnderlyingMajorVersion = osvi.dwMajorVersion; 
  243.           lpVersionInformation->dwUnderlyingMinorVersion = osvi.dwMinorVersion; 
  244.           lpVersionInformation->dwUnderlyingBuildNumber = LOWORD(osvi.dwBuildNumber); //ignore HIWORD
  245.           lpVersionInformation->dwUnderlyingPlatformId = osvi.dwPlatformId;
  246.           strcpy(lpVersionInformation->szUnderlyingCSDVersion, osvi.szCSDVersion);
  247.           
  248.           //Explicitely map the win32 dwPlatformId to our own values
  249.           if (lpVersionInformation->dwEmulatedPlatformId == VER_PLATFORM_WIN32s)
  250.             lpVersionInformation->dwEmulatedPlatformId = PLATFORM_WIN32S;
  251.           else if (lpVersionInformation->dwEmulatedPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  252.             lpVersionInformation->dwEmulatedPlatformId = PLATFORM_WINDOWS95;
  253.           if (lpVersionInformation->dwEmulatedPlatformId == VER_PLATFORM_WIN32_NT)
  254.             lpVersionInformation->dwEmulatedPlatformId = PLATFORM_NT_WORKSTATION;
  255.  
  256.           bFoundUnderlyingOS = TRUE;
  257.         }
  258.       }
  259.       WOWFreeLibrary32(hInstKrnl32);
  260.  
  261.       if (!bFoundUnderlyingOS)
  262.       {
  263.         //must be running on a real version of 16 bit Windows whose underlying OS is DOS
  264.         lpVersionInformation->dwUnderlyingMajorVersion = HIBYTE(HIWORD(dwVersion)); 
  265.         lpVersionInformation->dwUnderlyingMinorVersion = LOBYTE(HIWORD(dwVersion)); 
  266.         lpVersionInformation->dwUnderlyingBuildNumber = 0; 
  267.         lpVersionInformation->dwUnderlyingPlatformId = PLATFORM_DOS;
  268.         strcpy(lpVersionInformation->szUnderlyingCSDVersion, "MS-DOS");
  269.       }
  270.     #else //Must be some version of real or emulated Dos
  271.       
  272.       //Retreive the current version of emulated dos
  273.       BYTE DosMinor;
  274.       BYTE DosMajor;
  275.       _asm
  276.       {
  277.         mov ax, 3306h
  278.         int 21h
  279.         mov byte ptr [DosMajor], bl
  280.         mov byte ptr [DosMinor], bh
  281.       }
  282.       lpVersionInformation->dwEmulatedPlatformId = PLATFORM_DOS;
  283.       lpVersionInformation->dwEmulatedMajorVersion = (DWORD) DosMajor; 
  284.       lpVersionInformation->dwEmulatedMinorVersion = (DWORD) DosMinor;                
  285.       lpVersionInformation->dwEmulatedBuildNumber = 0; //no build number with Dos
  286.  
  287.       //We can detect if NT is running as it reports Dos v5.5
  288.       if ((lpVersionInformation->dwEmulatedMajorVersion == 5) &&
  289.           (lpVersionInformation->dwEmulatedMinorVersion == 50))    //NT reports Dos v5.5
  290.       {
  291.         _fstrcpy(lpVersionInformation->szUnderlyingCSDVersion, "Microsoft Windows NT");    
  292.         //could not find method of determing version of NT from Dos,
  293.         //so assume 3.50
  294.         lpVersionInformation->dwUnderlyingMajorVersion = 3; 
  295.         lpVersionInformation->dwUnderlyingMinorVersion = 50; 
  296.         lpVersionInformation->dwUnderlyingBuildNumber = 0;  //cannot get access to build number from Dos
  297.         lpVersionInformation->dwUnderlyingPlatformId = PLATFORM_NT_WORKSTATION;
  298.       }            
  299.       else if (lpVersionInformation->dwEmulatedMajorVersion >= 7) //Win95 reports Dos v7.00
  300.       {
  301.         _fstrcpy(lpVersionInformation->szUnderlyingCSDVersion, "Microsoft Windows 95");
  302.         lpVersionInformation->dwUnderlyingMajorVersion = 4; 
  303.         lpVersionInformation->dwUnderlyingMinorVersion = 0; 
  304.         lpVersionInformation->dwUnderlyingBuildNumber = 0;  //cannot get access to build number from Dos
  305.         lpVersionInformation->dwUnderlyingPlatformId = PLATFORM_WINDOWS95;              
  306.       }  
  307.       else
  308.       {
  309.         //need to get the underlying OS here here via the int 2FH interface of Windows
  310.         GetWinInfo();
  311.         if (bRunningWindows)
  312.         {                   
  313.           //Could not find method of differentiating between WFW & Win3.1 under Dos,
  314.           //so assume Win3.1
  315.           lpVersionInformation->dwUnderlyingPlatformId = PLATFORM_WINDOWS;      
  316.           _fstrcpy(lpVersionInformation->szUnderlyingCSDVersion, "Microsoft Windows");
  317.           lpVersionInformation->dwUnderlyingMajorVersion = HIBYTE(WinVer); 
  318.           lpVersionInformation->dwUnderlyingMinorVersion = LOBYTE(WinVer); 
  319.           lpVersionInformation->dwUnderlyingBuildNumber = 0;  //cannot get access to build number from Dos
  320.  
  321.         }
  322.         else //must be on a real version of Dos
  323.         {                               
  324.           lpVersionInformation->dwUnderlyingMajorVersion = (DWORD) DosMajor; 
  325.           lpVersionInformation->dwUnderlyingMinorVersion = (DWORD) DosMinor;                
  326.           lpVersionInformation->dwUnderlyingBuildNumber = 0; //no build number with Dos
  327.           lpVersionInformation->dwUnderlyingPlatformId = PLATFORM_DOS;
  328.           _fstrcpy(lpVersionInformation->szUnderlyingCSDVersion, "MS-DOS");
  329.         }
  330.       }  
  331.     #endif  
  332.   #endif
  333.  
  334.   return TRUE;
  335. }
  336.                                   
  337.                                   
  338.       
  339.       
  340. #ifdef _WIN32      
  341. BOOL WhichNTProduct(DWORD dwVersion)
  342. {
  343.   const int MY_BUFSIZE = 100;
  344.   TCHAR szProductType[MY_BUFSIZE];
  345.   DWORD dwBufLen = MY_BUFSIZE * sizeof(TCHAR);
  346.   HKEY hKey;
  347.  
  348.   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  349.                   _T("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
  350.                   0,
  351.                   KEY_EXECUTE,
  352.                   &hKey) != ERROR_SUCCESS) 
  353.     return FALSE;
  354.  
  355.   if (RegQueryValueEx(hKey,
  356.                      _T("ProductType"),
  357.                      NULL,
  358.                      NULL,
  359.                      (LPBYTE) szProductType,
  360.                      &dwBufLen) != ERROR_SUCCESS)
  361.     return FALSE;
  362.  
  363.   RegCloseKey(hKey);
  364.         
  365.   BOOL bSuccess = FALSE;
  366.  
  367.   // check product options, in order of likelihood   strcmp
  368.   if (_tcscmp(_T("WINNT"), szProductType) == 0) 
  369.   {
  370.     dwVersion = PLATFORM_NT_WORKSTATION;
  371.     bSuccess = TRUE;
  372.   }  
  373.   else if (_tcscmp(_T("SERVERNT"), szProductType) == 0) 
  374.   {
  375.     dwVersion = PLATFORM_NT_SERVER;
  376.     bSuccess = TRUE;
  377.   }  
  378.   else if (_tcscmp(_T("LANMANNT"), szProductType) == 0) 
  379.   {
  380.     dwVersion = PLATFORM_NT_ADVANCEDSERVER;
  381.     bSuccess = TRUE;
  382.   }  
  383.  
  384.   return bSuccess;
  385. }
  386. #endif                                  
  387.                                    
  388.  
  389. #if defined(_WINDOWS) && !defined(_WIN32)
  390. DWORD WINAPI WOWGetCaps32(VOID)
  391. {
  392.   return dwCapBits;
  393. }     
  394.  
  395.  
  396. UINT WINAPI WOWCreateVDMPointer16(DWORD dwLinBase, DWORD dwLimit)
  397. {
  398.   UINT uSelector, uDSSel;
  399.  
  400.   if (!(dwCapBits & WOW_VDMPTR16))
  401.     return NULL;
  402.  
  403.   // Grab our DS (for access rights)
  404.   __asm mov uDSSel, ds
  405.  
  406.   // Allocate a new selector
  407.   uSelector = AllocSelector(uDSSel);
  408.   if (uSelector)
  409.   {
  410.     // Assign its linear base address and limit
  411.     SetSelectorBase(uSelector, dwLinBase);
  412.     SetSelectorLimit(uSelector, dwLimit);
  413.   }
  414.   return uSelector;
  415. }
  416.  
  417.  
  418. UINT WINAPI WOWDeleteVDMPointer16(UINT uSelector)
  419. {
  420.   if (!(dwCapBits & WOW_VDMPTR16))
  421.     return NULL;
  422.   return FreeSelector(uSelector);
  423. }
  424.  
  425.  
  426. HWND32 WINAPI WOWHwndToHwnd32(HWND hWnd)
  427. {
  428.   if (!(dwCapBits & WOW_HWND32))
  429.     return NULL;
  430.   
  431.   // OR mask the upper 16 bits
  432.   HWND32 hWnd32 = (HWND32) (WORD) (hWnd);
  433.   return (hWnd32 | 0xffff0000);
  434. }
  435.  
  436.  
  437. HINSTANCE32 WINAPI WOWLoadLibraryEx32(LPSTR lpszFile, HFILE32 hFile,
  438.                                                DWORD dwFlags)
  439. {
  440.   if (!(dwCapBits & WOW_LOADLIBRARY))
  441.     return NULL;
  442.  
  443.   return LoadLibraryEx32W(lpszFile, hFile, dwFlags);
  444. }
  445.  
  446.  
  447. BOOL WINAPI WOWFreeLibrary32(HINSTANCE32 hInst32)
  448. {
  449.   if (!(dwCapBits & WOW_FREELIBRARY))
  450.     return NULL;
  451.  
  452.   return FreeLibrary32W(hInst32);
  453. }
  454.  
  455.  
  456. FARPROC WINAPI WOWGetProcAddress32(HINSTANCE32 hInst32,
  457.                                             LPCSTR lpszProc)
  458. {
  459.   if (!(dwCapBits & WOW_GETPROCADDRESS))
  460.     return NULL;
  461.   return GetProcAddress32W(hInst32, lpszProc);
  462. }
  463.  
  464.  
  465. DWORD WINAPI WOWGetVDMPointer32(LPVOID lpAddress, UINT fMode)
  466. {
  467.   if (!(dwCapBits & WOW_VDMPTR32))
  468.     return NULL;
  469.   return GetVDMPointer32W(lpAddress, fMode);
  470. }
  471.  
  472.  
  473. DWORD WOWCallProc32(FARPROC lpfnFunction, DWORD dwAddressConvert, DWORD dwParams, ...)
  474. {
  475.   va_list vaList;
  476.   DWORD   dwCount;
  477.   DWORD   dwTemp;
  478.  
  479.   if (!(dwCapBits & WOW_CALLPROC))
  480.     return NULL;
  481.  
  482.   // Variable list start
  483.   va_start(vaList,dwParams);
  484.  
  485.   for(dwCount=0; dwCount < dwParams; dwCount++)
  486.   {
  487.     // Pull each variable off of the stack
  488.     dwTemp=(DWORD)va_arg(vaList,DWORD);
  489.  
  490.     // Push the DWORD
  491.     __asm push word ptr [dwTemp+2];
  492.     __asm push word ptr [dwTemp];
  493.   }
  494.   // Variable list end
  495.   va_end(vaList);
  496.  
  497.   // Call Win32.  The pushed variable list precedes the parameters.
  498.   // Appropriate parameters will be popped by this function (based
  499.   // on the value in dwParams)
  500.   return CallProc32W(lpfnFunction, dwAddressConvert, dwParams);
  501. }
  502.  
  503.  
  504. BOOL WFWLoaded()
  505. {
  506.   const WORD WNNC_NET_MultiNet         = 0x8000;
  507.   const WORD WNNC_SUBNET_WinWorkgroups = 0x0004;
  508.   const WORD WNNC_NET_TYPE             = 0x0002;
  509.   BOOL rVal;
  510.    
  511.   HINSTANCE hUserInst = LoadLibrary("USER.EXE");
  512.   lpfnWNetGetCaps lpWNetGetCaps = (lpfnWNetGetCaps) GetProcAddress(hUserInst, "WNetGetCaps");
  513.   if (lpWNetGetCaps != NULL)
  514.   {
  515.     // Get the network type
  516.     WORD wNetType = lpWNetGetCaps(WNNC_NET_TYPE);
  517.     if (wNetType & WNNC_NET_MultiNet)
  518.     {
  519.       // a multinet driver is installed
  520.       if (LOBYTE(wNetType) & WNNC_SUBNET_WinWorkgroups) // It is WFW
  521.         rVal = TRUE;
  522.       else // It is not WFW
  523.         rVal = FALSE;
  524.     }
  525.     else
  526.      rVal = FALSE;
  527.   }
  528.   else
  529.     rVal = FALSE;
  530.    
  531.   // Clean up the module instance
  532.   if (hUserInst)
  533.     FreeLibrary(hUserInst);
  534.     
  535.   return rVal;  
  536. }
  537.  
  538. #endif //defined(_WINDOWS) && !defined(_WIN32)
  539.  
  540.  
  541.  
  542.              
  543. #ifdef _DOS             
  544. void GetWinInfo()
  545.   //use some inline assembly to determine if Windows if
  546.   //running and what version is active
  547.   _asm
  548.   {
  549.   ; check for Windows 3.1
  550.     mov     ax,160ah                ; WIN31CHECK
  551.     int     2fh                     ; check if running under Win 3.1.
  552.     or      ax,ax
  553.     jz      RunningUnderWin31       ; can check if running in standard
  554.                                     ; or enhanced mode
  555.    
  556.   ; check for Windows 3.0 enhanced mode
  557.     mov     ax,1600h                ; WIN386CHECK
  558.     int     2fh
  559.     test    al,7fh
  560.     jnz     RunningUnderWin30Enh    ; enhanced mode
  561.    
  562.   ; check for 3.0 WINOLDAP
  563.     mov     ax,4680h                ; IS_WINOLDAP_ACTIVE
  564.     int     2fh
  565.     or      ax,ax                   ; running under 3.0 derivative?
  566.     jnz     NotRunningUnderWin
  567.    
  568.   ; rule out MS-DOS 5.0 task switcher
  569.     mov     ax,4b02h                ; detect switcher
  570.     push    bx
  571.     push    es
  572.     push    di
  573.     xor     bx,bx
  574.     mov     di,bx
  575.     mov     es,bx
  576.     int     2fh
  577.     pop     di
  578.     pop     es
  579.     pop     bx
  580.     or      ax,ax
  581.     jz      NotRunningUnderWin      ; MS-DOS 5.0 task switcher found
  582.    
  583.   ; check for standard mode Windows 3.0
  584.     mov     ax,1605h                ; PMODE_START
  585.     int     2fh
  586.     cmp     cx,-1
  587.     jz      RunningUnderWin30Std
  588.    
  589.   ; check for real mode Windows 3.0
  590.     mov     ax,1606h                ; PMODE_STOP
  591.     int     2fh                     ; in case someone is counting
  592.     ; Real mode Windows 3.0 is running
  593.     mov     byte ptr [bRunningWindows], 1
  594.     mov     word ptr [WinVer], 0300h
  595.     jmp     ExitLabel
  596.    
  597.   RunningUnderWin30Std:
  598.     ; Standard mode Windows 3.0 is running
  599.     mov     byte ptr [bRunningWindows], 1
  600.     mov     word ptr [WinVer], 0300h
  601.     jmp     ExitLabel
  602.    
  603.   RunningUnderWin31:
  604.     ; At this point: CX == 3 means Windows 3.1 enhanced mode
  605.     ;                CX == 2 means Windows 3.1 standard mode
  606.     mov     byte ptr [bRunningWindows], 1
  607.     mov     word ptr [WinVer], 0310h    
  608.     jmp     ExitLabel
  609.    
  610.   RunningUnderWin30Enh:
  611.     ; Enhanced mode Windows 3.0 is running
  612.     mov     byte ptr [bRunningWindows], 1    
  613.     mov     word ptr [WinVer], 0300h    
  614.     jmp     ExitLabel
  615.    
  616.   NotRunningUnderWin:                    
  617.     mov     byte ptr [bRunningWindows], 0
  618.     
  619.   ExitLabel:
  620.   } 
  621.  
  622. #endif //_DOS 
  623.